package com.opal.modules.costReportForm.service.impl;

import com.opal.consts.CommonConst;
import com.opal.consts.WSC;
import com.opal.domain.R;
import com.opal.domain.ReturnMessageData;
import com.opal.model.DataGridData;
import com.opal.modules.costReportForm.constant.CRF;
import com.opal.modules.costReportForm.entity.AcMail;
import com.opal.modules.costReportForm.entity.ActivitiUser;
import com.opal.modules.costReportForm.entity.CostReport;
import com.opal.modules.costReportForm.entity.TaskProgressChart;
import com.opal.modules.costReportForm.entity.table.CostApprovals;
import com.opal.modules.costReportForm.entity.table.CostApprovalsExample;
import com.opal.modules.costReportForm.entity.table.CostSignature;
import com.opal.modules.costReportForm.entity.table.OpalUserProcinst;
import com.opal.modules.costReportForm.mapper.activiti.ActivitiMapper;
import com.opal.modules.costReportForm.mapper.mysql.CostApprovalsMapper;
import com.opal.modules.costReportForm.mapper.mysql.OpalUserProcinstMapper;
import com.opal.modules.costReportForm.mapper.oracle.QueryManagerMapper;
import com.opal.modules.costReportForm.model.CompletionTask;
import com.opal.modules.costReportForm.service.ApprovalTaskService;
import com.opal.modules.costReportForm.service.CostCommonService;
import com.opal.modules.costReportForm.service.CostReportFormService;
import com.opal.system.entity.table.OpalUser;
import com.opal.system.entity.table.OpalUserExample;
import com.opal.system.mapper.mysql.OpalUserMapper;
import com.opal.system.service.OpalUserService;
import com.opal.utils.ResultMsg;
import com.opal.utils.UserUtils;
import lombok.extern.slf4j.Slf4j;
import org.activiti.engine.*;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricProcessInstanceQuery;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.history.HistoricTaskInstanceQuery;
import org.activiti.engine.impl.identity.Authentication;
import org.activiti.engine.impl.persistence.entity.HistoricProcessInstanceEntity;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.runtime.ProcessInstanceQuery;
import org.activiti.engine.task.Task;
import org.activiti.engine.task.TaskQuery;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;

@Service
@Slf4j
public class ApprovalTaskServiceImpl implements ApprovalTaskService {

    @Autowired
    private ProcessEngine processEngine;
    @Autowired
    private RuntimeService runtimeService;
    @Resource
    private AcMail mail;
    @Autowired
    private OpalUserService opalUserService;
    @Autowired
    private OpalUserMapper opalUserMapper;
    @Autowired
    private OpalUserProcinstMapper opalUserProcinstMapper;
    @Autowired
    @Lazy  //由于这个包是和本类是循环引用的，加入了aop的包后，启动会报错，在互相依赖的随便一个bean上加上@Lazy注解。
    private CostReportFormService costReportForcmService;
    @Autowired
    private CostApprovalsMapper costApprovalsMapper;
    @Autowired
    private ActivitiMapper activitiMapper;
    @Autowired
    private CostCommonService costCommonService;

    //提交审批
    @Override
    @Transactional(value = "mysqlTransactionManager")
    public ReturnMessageData submitFileService(String id, String ProcessKey, String saleType)throws Exception{  //id：成品报告单据号,saleType:判断财务需要用到的类型

        //准备启动流程
        //判断成本报告是否已在审批中
        ProcessInstanceQuery processInstanceQuery = runtimeService.createProcessInstanceQuery();
        List<ProcessInstance> lists = processInstanceQuery.processInstanceBusinessKey(id).list();
        if (lists.size()>0){
            return new ReturnMessageData(WSC.PRECONDITIONFAILED, "此成本报告已在审批中！");
        }

        //判断用户
        OpalUser user=UserUtils.getSessionUser();
        Long userId = user.getUserId();// 获取当前用户id
        String userName=user.getUserName();
        if (userId == null) {
            return new ReturnMessageData(WSC.REQUEST_UNAUTHORIZED, "请先登录！");
        }

        // 设置流程启动人
        Authentication.setAuthenticatedUserId(userName);

        //1、设置变量:邮箱地址 和 id(负责人) ：申请人，项目经理，部门经理，总经理，总裁 ，财务等，2、判断当前用户账户的相关信息
        ActivitiUser activitiUser = this.getUserPostService(saleType,user);

        //设置项目经理邮箱内容
        //String html="你有一份【成本报告表】需要您的审批，请您尽快登录澳宝管理系统-成本报告-审批，单据号为：";
        //设置邮箱内容
        mail.setHtml(CRF.disposeMailContent(costReportForcmService.getCostReport(id)));

        //为流程图中变量赋值
        Map<String, Object> map = new HashMap<>();
        map.put("activitiUser", activitiUser);
        map.put("acMail", mail);
        map.put("pkOrg", user.getPkOrg());

        // 启动流程
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(ProcessKey, id, map);
        String processInstanceId = processInstance.getId(); // 获取流程实例id:act_hi_procinst表中 id

        // 根据任务id完成任务
        TaskService taskService = processEngine.getTaskService();

        // 插入opal_user_procinst关系表中用于记录每个用户所启动的实例
        int num = insertUserprocinst(userId, processInstanceId, "exportCost");
        if (num <= 0) {
            throw new Exception("插入opal_user_procinst失败！");
        }

        //插入关联表：CostApprovals：申请人信息   0提交
        insertCostApprovals(id, userName, processInstanceId, 0);
        // 获取当前任务id
        String taskId = getCurrentTaskId(processInstanceId);

        // 根据当前任务id完成任务
        taskService.complete(taskId);
        //插入关联表：CostApprovals：项目经理信息
        CostApprovals costApprovals = insertCostApprovals(id, userName, processInstanceId, -1);

        log.info("启动流程成功,流程实例id为：" + costApprovals.getApprovalsProcinst());

        return new ReturnMessageData(WSC.RESTPONSE_OK, "成本报告表提交申请成功！");
    }

    //处理审批过程
    @Override
    @Transactional(transactionManager = "mysqlTransactionManager", rollbackFor = {Exception.class, ActivitiException.class})
    public ReturnMessageData approvalProcessService(CostApprovals costApprovals, Integer num, Integer result,Integer resubmit) {
        TaskService taskService = processEngine.getTaskService();
        String processInstanceId = costApprovals.getApprovalsProcinst();
        String taskId = costApprovals.getApprovalsTaskId();
    
        //根据当前实例id获取当前任务
        List<Task> taskItem = selectCurrentTaskItem(processInstanceId, null);

        //判断用户
        OpalUser sessionUser = UserUtils.getSessionUser();//获取用户信息
        if (sessionUser == null) {
            return new ReturnMessageData(WSC.REQUEST_UNAUTHORIZED, "请先登录！");
        }

        //判断任务:若有并行网关就会有两个任务
        boolean flag=true;
        //判断当前用户是否是负责人
        boolean flag1=true;
        String assignee="";
        for (Task task:taskItem){
            if (task.getId().equals(taskId)) {
                flag=false;
            }
            //负责人
           String name= task.getAssignee();
            if ((sessionUser.getUserId() + "").equals(name)){
                assignee=name;
                flag1=false;
            }

        }
        if (flag){
            return new ReturnMessageData(WSC.PRECONDITIONFAILED, "审批失败：没有此任务或此任务已审批");
        }
        if (flag1){
            return new ReturnMessageData(WSC.PRECONDITIONFAILED, "抱歉你不是当前任务审批人！");
        }

        try {

            //获取流程中的变量
            Map<String, Object> map = runtimeService.getVariables(processInstanceId);
            ActivitiUser activitiUser = (ActivitiUser) map.get("activitiUser");
            AcMail acMail = (AcMail) map.get("acMail");

            //成本报告版本
            String business = getBusiness(processInstanceId);
            CostReport costReport = costReportForcmService.getCostReport(business);

            int rStatus = 1;     //CostApprovals表中的状态：0：初始提交状态，1、同意，2、驳回，3、拒绝，4、审批流完成状态，5、重新修改 -1、处理中,6财务

            //判断节点走向：1、同意：需要发送邮箱告知下一个负责人审批
            if (num == 1) {        // 走下一个负责人邮箱
                CostSignature costSignature = new CostSignature();
                costSignature.setCostReportId(business);

                //设置申请人的邮箱内容：由于邮箱内容中要获取审批人的姓名这里必须每个节点都要走
                acMail.setHtml2(CRF.disposeMailContentAgree(opalUserMapper.selectByPrimaryKey(Long.parseLong(assignee)).getUserName(),costReport));

                //项目经理
                if(assignee.equals(activitiUser.getTaskName1())){
                    //设置审批人的邮箱内容：由于都是相同的内容；在这个节点只设置一次
                    acMail.setHtml(CRF.disposeMailContent(costReport));

                    //在业务经理这里设置整套毛利 ：整个流程只有拒绝直接到审批人才可以进行修改操作；可以在这里节点来设置
                    map.put("grossMarginRate", costReport.getGrossMarginRate().doubleValue());            //设置整套毛利

                    //往cost_signature表中插入当前经理的名字，用于锐浪报表的签名
                    costSignature.setXmjl(UserUtils.getSessionUser().getUserName());
                }

                //部门经理
                if (assignee.equals(activitiUser.getTaskName2())) {
                    String saleType = costReport.getSaleType();
                    //saleType销售类型(内销，外销)：用于判断发送给哪个类型财务, 申请人id
                    map.put("saleType",saleType);                       //设置内销还是外销

                    //赋值财务信息：邮箱和负责人
                    // 1、根据成本报告表的公司账套的类型(内销外销)人员
                    // 2、澳宝管理系统设置的财务用户中有几个人来随意分配人数(最多三人)
                    financeValuation(acMail,activitiUser,saleType,costReport);

                    //为财务邮箱设置内容
                    acMail.setCaiWuHtml(CRF.disposeMailContentReception(costReport));

                    //往cost_signature表中插入当前经理的名字，用于锐浪报表的签名
                    costSignature.setBmjl(UserUtils.getSessionUser().getUserName());
                }

                //总经理
                if (assignee.equals(activitiUser.getTaskName3())){

                    //往cost_signature表中插入当前经理的名字，用于锐浪报表的签名
                    costSignature.setZjl(UserUtils.getSessionUser().getUserName());
                }

                //总裁
                if (assignee.equals(activitiUser.getTaskName4())) {

                    //往cost_signature表中插入当前经理的名字，用于锐浪报表的签名
                    costSignature.setZc(UserUtils.getSessionUser().getUserName());
                }

                //插入和更新cost_signature（经理签名表）操作，若成本报告单据号在数据库有值，则进行更新
                costCommonService.insertCostSignatureService(costSignature);

                map.put("num", num);
                map.put("result", 1);

                //最终成本报告审批：条件总经理毛利等于大于20或总裁
                Object grossMarginRate= map.get("grossMarginRate");
                double grossMarginRateValue =0;
                //这里只能进行判断类型了:不能乱更改流程了，不然新旧流程中的变量又不一致，后续旧流程走完可以删掉判断类型的操作
                if (grossMarginRate!=null){
                    if(grossMarginRate instanceof Double){
                        grossMarginRateValue=(Double)grossMarginRate;
                    }
                    if (grossMarginRate instanceof  BigDecimal)
                    grossMarginRateValue = ((BigDecimal) grossMarginRate).doubleValue();
                }


                if (assignee.equals(activitiUser.getTaskName4()) || (assignee.equals(activitiUser.getTaskName3()) && grossMarginRateValue >= 20)) {    //指定TaskName4就是总裁，
                    //更改状态成本报告状态：审核状态:0未审核 ,1审核通过 ,2审核不通过,3审核中
                    acMail.setHtml2(CRF.disposeMailContentFinish(costReport));
                    //成本报告最终状态
                    finalAuditStatus(processInstanceId, 1);
                    rStatus = 4;

                }else{

                    //前端传回变量为resubmit=666，证明是重新提交
                    if (resubmit==666){
                        //成功报告更改为审核状态
                        finalAuditStatus(processInstanceId, 3);
                        //审批状态更改为：重新提交
                        rStatus = 5;
                    }
                }
            }  else if (num == 0) {  //拒绝
                //根据当前成本报告单据号删除cost_signature表中的数据，清除锐浪报表签名的名字
                costCommonService.deleteCostSignatureService(business);
                //设置拒绝邮箱内容
                acMail.setJuJueHtml( CRF.disposeMailContentRepulse(opalUserMapper.selectByPrimaryKey(Long.parseLong(assignee)).getUserName(),costReport));
                //更改状态成本报告状态：审核状态:0未审核 ,1审核通过 ,2审核不通过,3审核中
                finalAuditStatus(processInstanceId, 2);
                map.put("num", 0);
                map.put("result", 0);
                rStatus = 3;    //审批人拒绝
            }

            //若等于内销财务或者外销财务状态改为6，已经接收
            if (assignee.equals(activitiUser.getNeiXiaoCaiWu()) || assignee.equals(activitiUser.getNeiXiaoCaiWu2()) || assignee.equals(activitiUser.getWaiXiaoCaiWu())){
                rStatus = 6;
            }
            //修改cost_approvals 当前任务状态
            updateStatus(processInstanceId, taskId, rStatus, costApprovals.getApprovalsAuditopinion());
            //完成任务
            taskService.complete(taskId, map);

            //审批状态：插入表cost_approvals，默认状态都是处理中：-1，CostApprovals表中的状态：0：初始提交状态，1、同意，2、驳回，3、拒绝，4、审批流完成状态，5、重新修改 -1、处理中,6财务
            insertCostApprovals(business, costApprovals.getApprovalsProposer(), processInstanceId, -1);

        } catch (ActivitiException e) {
            e.printStackTrace();
            String message=e.getMessage();
            if (message.contains("sending email")) {
                throw new RuntimeException("审批处理失败：下一节审批人未设置邮箱或邮箱不正确，发送邮箱失败！");
            }
            if (message.contains("Unknown property used in expression")){
                throw new RuntimeException("流程中必须的值未赋值:"+message);
            }
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }

        return new ReturnMessageData(WSC.RESTPONSE_OK, "审批处理完成！");
    }

    @NotNull
    private CostApprovals insertCostApprovals(String business, String userName, String processInstanceId, int status) {
        // 返回当前任务详情:
        List<Task> lists = selectCurrentTaskItem(processInstanceId, null);
        CostApprovals costApprovals = new CostApprovals();
        for(Task list:lists) {
                long userId = Long.parseLong(list.getAssignee());
                // 存储到cost_approvals表中
                costApprovals.setApprovalsTaskId(list.getId());                        //任务id
                costApprovals.setApprovalsProcinst(processInstanceId);                        //流程实例id
                costApprovals.setApprovalsStatus(status);                                    //状态
                costApprovals.setApprovalsReceipts(business);                                //成本报告版本
                costApprovals.setApprovalsProposer(userName);                                //申请人
                costApprovals.setApprovalsDescription("审核成本报告表");                        //申请要求
                costApprovals.setUserId(userId);                                                //任务负责人
                OpalUser user = opalUserMapper.selectByPrimaryKey(userId);
                if (user !=null){
                    costApprovals.setApprovalsName(user.getUserName());                         //任务姓名
                }else {
                    log.error("在处理CostApprovals表的字段姓名根据用户id未查询到相关的用户");
                }

                costApprovals.setApprovalsNum((disposeProgress(processInstanceId) + 1));            //插入
                costApprovalsMapper.insertSelective(costApprovals);
        }
        return costApprovals;
    }

    //统计进度已有几条
    public Integer disposeProgress(String processInstanceId) {
        CostApprovalsExample costApprovalsExample = new CostApprovalsExample();
        costApprovalsExample.createCriteria().andApprovalsProcinstEqualTo(processInstanceId);
        int i = costApprovalsMapper.countByExample(costApprovalsExample);
        return i;
    }

    //查询：个人提交的任务
    @Override
    public Object querySelfSubmiTtaskService(int page,int rows) {
        String userName = UserUtils.getSessionUser().getUserName();
        if (userName != null) {
            try {
                //根据历史过程实例对象来查询
                HistoricProcessInstanceQuery hpi = processEngine.getHistoryService()
                        .createHistoricProcessInstanceQuery()               //创建历史流程实例查询
                        .startedBy(userName)                                //条件一：设置启动流程的人，自己定义的是用户姓名
                        .orderByProcessInstanceStartTime()
                        .desc();
                //根据分页查询
                List<HistoricProcessInstance> historicProcessInstances = hpi.listPage((page - 1) * rows, rows);
                DataGridData<List<HistoricProcessInstance>> dataGrid= new DataGridData<>();

                for (HistoricProcessInstance l:historicProcessInstances){
                    HistoricProcessInstanceEntity hi=(HistoricProcessInstanceEntity)l;//强转成实现类

                    String businessKey = l.getBusinessKey();
                    CostReport costReport = costReportForcmService.getCostReport(businessKey);//这个效率超级低啊，以后很多就惨了，(幸亏上面刷出的数据是分页)
                    if (costReport !=null){
                        hi.setId(costReport.getFinishedProductCode());//往Description成员变量赋值：物料品号，单纯用于展示用,这框架后期肯定有做处理的
                        hi.setName(costReport.getProductName()); //赋值成品名称
                        hi.setLocalizedDescription(costReport.getRealityQuotedPrice()+"");//实际报价
                        hi.setDeploymentId(costReport.getGrossMarginMoney()+"");//整体毛利
                        hi.setTenantId(costReport.getGrossMarginRate()+""); //整体毛利率
                    }

                }
                dataGrid.setRows(historicProcessInstances);
                //获取不在分页条件下的总条数
                long count = hpi.count();
                dataGrid.setTotal((int) count);
                return dataGrid;

            } catch (ActivitiIllegalArgumentException e) {
                e.printStackTrace();
                System.out.println("Set of process instance ids is empty");
            }

        }
        return null;
    }

    //查询：已完成的任务
    public Object queryCompletionTaskService(int page,int rows) {
        // 获取session中的id
        Long sessionUserId = UserUtils.getSessionUserId();

        if (sessionUserId != null) {
            try {
                //获取任务信息
                HistoricTaskInstanceQuery hpi = processEngine.getHistoryService()
                        .createHistoricTaskInstanceQuery()      //创建历史任务实例查询
                        .taskAssignee(sessionUserId + "")       // 条件一：负责人
                        .finished()                             //条件二：只查询已完成的任务
                        .orderByHistoricTaskInstanceEndTime()
                        .desc();
                Set<CompletionTask> completionTasks=new HashSet<>();
                DataGridData<List<CompletionTask>> dataGrid= new DataGridData<>();
                List<HistoricTaskInstance> historicTaskInstances = hpi.listPage((page - 1) * rows, rows);
                //刷掉重复的：同一个流程实例拒绝后又重新审批的就会有重复的,暂时使用重写set集合进行处理，造成问题是浏览器显示的是乱序
                for (HistoricTaskInstance h:historicTaskInstances){
                    CompletionTask completionTask=new CompletionTask();
                    //业务id：成本报告单据
                    String processInstanceId = h.getProcessInstanceId();
                    String busines = getBusiness(processInstanceId);
                    CostReport costReport = costReportForcmService.getCostReport(busines);//这个效率超级低啊，以后很多就惨了，(幸亏上面刷出的数据是分页)
                    if (costReport !=null){
                        completionTask.setFinishedProductCode(costReport.getFinishedProductCode());//往Description成员变量赋值：物料品号，单纯用于展示用
                        completionTask.setProductName(costReport.getProductName()); //赋值成品名称
                        completionTask.setRealityQuotedPrice(costReport.getRealityQuotedPrice()+""); //实际报价
                        completionTask.setGrossMarginMoney(costReport.getGrossMarginMoney()+"");    //整体毛利
                        completionTask.setGrossMarginRate(costReport.getGrossMarginRate()+"");      //整体毛利率
                    }
                    completionTask.setCostPostId(busines);
                    completionTask.setStartTime(h.getStartTime());
                    completionTask.setEndTime(h.getEndTime());
                    completionTask.setProcessInstanceId(processInstanceId);
                    completionTask.setProposerName(getStartUserName(processInstanceId));
                    completionTasks.add(completionTask);

                }
                //转换为list
                List<CompletionTask> resultData=new ArrayList<>(completionTasks);
                //根据获取时间进行排序
                Collections.sort(resultData,new Comparator<CompletionTask>(){

                    @Override
                    public int compare(CompletionTask o1, CompletionTask o2) {

                       Long num= o1.getStartTime().getTime()-o2.getStartTime().getTime();
                        if (num<0){
                            return 1;
                        }else if (num==0){
                            return 0;
                        }else {
                            return -1;
                        }

                    }
                });
                dataGrid.setRows(resultData);
                long count = hpi.count();
                dataGrid.setTotal((int) count);
                return dataGrid;

            } catch (ActivitiIllegalArgumentException e) {
                e.printStackTrace();
                System.out.println("Set of process instance ids is empty");
            }

        }
        return null;
    }

    @Override
    public Object queryHistoryProcessByBusiness(String business) {
        return activitiMapper.queryHistoryProcessByBusiness(business);
    }

    /**
     * 审批进度详情
     *
     * @param processInstanceId
     * @return
     */
    @Override
    public Object getAllProcessInstanceTaskService(String processInstanceId) {
        List<TaskProgressChart> result = new ArrayList<>();
        HistoryService historyService = processEngine.getHistoryService();
        List<HistoricTaskInstance> lists = historyService.createHistoricTaskInstanceQuery()
                .processInstanceId(processInstanceId)
                .orderByHistoricTaskInstanceStartTime().desc()
                .list();

        for (HistoricTaskInstance list : lists) {
            CostApprovalsExample costApprovalsExample = new CostApprovalsExample();
            CostApprovalsExample.Criteria criteria = costApprovalsExample.createCriteria();
            criteria.andApprovalsTaskIdEqualTo(list.getId())
                    .andApprovalsProcinstEqualTo(list.getProcessInstanceId())
                    .andUserIdEqualTo(Long.parseLong(list.getAssignee()));
            List<CostApprovals> costApprovals = costApprovalsMapper.selectByExample(costApprovalsExample);
            //
            if (costApprovals.size()>0){
                result.add(new TaskProgressChart(costApprovals.get(0).getApprovalsName(), list.getStartTime(),
                        list.getEndTime(), costApprovals.get(0).getApprovalsStatus(), list.getName(), costApprovals.get(0).getApprovalsAuditopinion()));

            }
        }

        return result;
    }

    //查询：审批任务信息

    @Override
    @Transactional(value = "mysqlTransactionManager", rollbackFor = Exception.class)
    public Object querySelfTaskService(String flowId) {
        //判断数据
        // 流程图定义key
        if (StringUtils.isBlank(flowId)) {
            flowId = "costReportProcess";
        }

        // 当前用户
        Long id = UserUtils.getSessionUserId();
        if (id == null) {
            throw new RuntimeException("请先登录！");
        }

        String assignee = id + "";
        try {
            //获取任务 ：根据条件流程图id和负责人获取
            TaskService taskService = processEngine.getTaskService();
            List<Task> list = taskService.createTaskQuery()
                    .processDefinitionKey(flowId)        //流程id
                    .taskAssignee(assignee)                //任务负责人
                    .list();
            List<Map<String, String>> maps = new ArrayList<>();
            //获取流程中的变量
            Map<String, Object> mapss = runtimeService.getVariables(list.get(0).getProcessInstanceId());
            ActivitiUser activitiUser = (ActivitiUser) mapss.get("activitiUser");
            for (Task task : list) {
                CostApprovalsExample costApprovalsExample = new CostApprovalsExample();
                CostApprovalsExample.Criteria criteria = costApprovalsExample.createCriteria();
                criteria.andUserIdEqualTo(id).andApprovalsTaskIdEqualTo(task.getId());
                List<CostApprovals> costApprovals = costApprovalsMapper.selectByExample(costApprovalsExample);
                //若没有值，证明不知道什么情况没有往CostApprovalsb表中插入值
                if(costApprovals.size()>0){
                    Integer approvalsNum = costApprovals.get(0).getApprovalsNum();
                    if (approvalsNum == null || approvalsNum - 1 < 1) {
                        approvalsNum = 1;
                    }
                    Map<String, String> map = new HashMap<>();
                    String busines = costApprovals.get(0).getApprovalsReceipts();
                    CostReport costReport = costReportForcmService.getCostReport(busines);//这个效率超级低啊，以后很多就惨了，(幸亏任务一般不会太多)
                    if (costReport !=null){
                        map.put("finishedProductCode",costReport.getFinishedProductCode());//往Description成员变量赋值：物料品号，单纯用于展示用
                        map.put("productName",costReport.getProductName()); //赋值成品名称
                        map.put("realityQuotedPrice", costReport.getRealityQuotedPrice()+"");
                        map.put("grossMarginMoney", costReport.getGrossMarginMoney()+"");
                        map.put("grossMarginRate", costReport.getGrossMarginRate()+"");
                    }
                    map.put("approvalsProposer", costApprovals.get(0).getApprovalsProposer());// 申请人
                    map.put("approvalsDescription", costApprovals.get(0).getApprovalsDescription());// 申请要求
                    map.put("approvalsReceipts", costApprovals.get(0).getApprovalsReceipts());// 申请单据
                    map.put("approvalsProcinst", costApprovals.get(0).getApprovalsProcinst());// 实例id
                    map.put("approvalsTaskId", costApprovals.get(0).getApprovalsTaskId());// 任务id
                    map.put("approvalsAuditopinion", miaoshu(approvalsNum, costApprovals.get(0).getApprovalsProcinst()));// 描述

                    //返回时财务的标识：改变页面的按钮
                    if (assignee.equals(activitiUser.getWaiXiaoCaiWu()) || assignee.equals(activitiUser.getWaiXiaoCaiWu2())|| assignee.equals(activitiUser.getWaiXiaoCaiWu3())
                            || assignee.equals(activitiUser.getNeiXiaoCaiWu()) || assignee.equals(activitiUser.getNeiXiaoCaiWu2())|| assignee.equals(activitiUser.getNeiXiaoCaiWu3())
                    ){
                        map.put("ccc","true");
                    }else {
                        map.put("ccc","");
                    }
                    maps.add(map);
                }else {
                  log.error("有审批任务未插入到cost_approvals表中，是配合此表查询任务信息的！");
                }

            }
            return maps;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("审批人id：【" + id + "】查询任务失败了");
        }
        return new ArrayList<>();
    }

    @Override
    public R deleteHistoryProcessByBusiness(String businessId){
        //查询的就是历史流程表
        List<HistoricProcessInstance> lists = activitiMapper.queryHistoryProcessByBusiness(businessId);
        if (lists!=null && lists.size()>0){
            for (HistoricProcessInstance list : lists) {
                String id = list.getId();
                //先结束流程：成功返回状态200
                R r = activitiMapper.deleteProcessInstance(id, "删除");
                //删除流程信息
                if (r.getStatus()==WSC.RESTPONSE_OK){
                    r = activitiMapper.deleteHistoryProcessInstance(id);
                    if (r.getStatus()== WSC.RESTPONSE_OK){
                        return new R(WSC.RESTPONSE_OK,"删除成功！");
                    }

                }
            }
        }

        return new R(WSC.RESTPONSE_OK,"删除失败！");
    }


    public String miaoshu(int approvalsNum, String approvalsProcinst) {
        CostApprovalsExample costApprovalsExample = new CostApprovalsExample();
        CostApprovalsExample.Criteria criteria = costApprovalsExample.createCriteria();

        //获取上一个审批人的信息：获取原因描述
        criteria.andApprovalsProcinstEqualTo(approvalsProcinst)
                .andApprovalsNumEqualTo(approvalsNum - 1);
        List<CostApprovals> c = costApprovalsMapper.selectByExample(costApprovalsExample);
        if (c.size() > 0) {
            return c.get(0).getApprovalsAuditopinion();
        } else {
            return "";
        }

    }

    //根据流程实例id：获取当前任务id
    public String getCurrentTaskId(String processInstanceId) {
        List<Task> task = selectCurrentTaskItem(processInstanceId, null);
        if (task == null || task.size() <= 0) {
            return null;
        }
        return task.get(0).getId();
    }

    public int insertUserprocinst(Long userid, String processInstanceId, String type) {
        OpalUserProcinst oup = new OpalUserProcinst();
        oup.setProcinstId(processInstanceId);
        oup.setType(type);
        oup.setUserId(userid);
        return opalUserProcinstMapper.insertSelective(oup);
    }

    //获取申请要求
    public String demand(String processDefinitionId) {
        RepositoryService repositoryService = processEngine.getRepositoryService();
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                .processDefinitionId(processDefinitionId)
                .singleResult();
        return processDefinition.getName();
    }

    /**
     * 查询当前任务获取详情：根据流程实例id和负责人(用户id)组合查询任务：
     */
    public List<Task> selectCurrentTaskItem(String processInstanceId, String assignee) {
        TaskService taskService = processEngine.getTaskService();
        TaskQuery taskQuery = taskService.createTaskQuery();
        if (processInstanceId != null) {
            taskQuery = taskQuery.processInstanceId(processInstanceId);
        } else if (assignee != null) {
            taskQuery = taskQuery.taskAssignee(assignee);//负责人
        }

        return taskQuery.list();
    }

    //修改：审核状态和审批人的意见
    public int updateStatus(String processInstanceId, String taskId, int status, String auditopinion) {

        CostApprovals costApprovals = new CostApprovals();
        costApprovals.setApprovalsStatus(status);                        //审核状态
        costApprovals.setApprovalsAuditopinion(auditopinion);            //意见
        CostApprovalsExample costApprovalsExample = new CostApprovalsExample();
        CostApprovalsExample.Criteria criteria = costApprovalsExample.createCriteria();
        criteria.andApprovalsTaskIdEqualTo(taskId)
                .andApprovalsProcinstEqualTo(processInstanceId);
        return costApprovalsMapper.updateByExampleSelective(costApprovals, costApprovalsExample);
    }

    //最终审核状态
    private ResultMsg finalAuditStatus(String processInstanceId, int i) {
        CostReport cr = new CostReport();
        cr.setCostReportId(getBusiness(processInstanceId));  //版本
        cr.setCostReportStatus(i);  //(1审核通过 ,2审核不通过)

        return costReportForcmService.updataCostReport(cr);
    }

    //根据流程实例id：获取当前负责人
    public String getCurrentTaskName(String processInstanceId) {
        List<Task> task = selectCurrentTaskItem(processInstanceId, null);
        if (task == null || task.size() <= 0) {
            return null;
        }
        return task.get(0).getAssignee();
    }

    //获取流程的启动人
    public String getStartUserName(String processInstanceId) {
        HistoricProcessInstance hpi = this.getHistoricProcessInstance(processInstanceId);
        String startUserId = hpi.getStartUserId();
        return startUserId;
    }

    //获取流程中的业务id
    public String getBusiness(String processInstanceId) {
        HistoricProcessInstance hpi = this.getHistoricProcessInstance(processInstanceId);
        String business = hpi.getBusinessKey();
        return business;
    }

    //获取 HistoricProcessInstance（流程实例的所有相关信息对象）
    public HistoricProcessInstance getHistoricProcessInstance(String processInstanceId) {
        HistoryService historyService = processEngine.getHistoryService();
        HistoricProcessInstance hpi = historyService.createHistoricProcessInstanceQuery()
                .processInstanceId(processInstanceId)                          //流程实例id
                .singleResult();
        return hpi;
    }

    /**
     * 根据员工部门获取当前所有的经理
     *
     * @return
     */
    private ActivitiUser getUserPostService(String saleType,OpalUser opalUser) {
        ActivitiUser activitiUser = new ActivitiUser();
        //1、获取申请人员工的部门和组织
        String pkOrg =null;
        String userDept = opalUser.getUserDept();
        if (opalUser !=null) {
            pkOrg = opalUser.getPkOrg();

            if (StringUtils.isBlank(pkOrg)){
                throw new RuntimeException("审批提交失败：请联系管理员，你的账户没有设置组织！");
            }

            //组织判断
            if (!pkOrg.equals(CommonConst.ZHAOTING) && !pkOrg.equals(CommonConst.AOBAO)){
                throw new RuntimeException("审批提交失败：你的账户组织不是兆婷或澳宝(惠州)");
            }

            //部门判断
            if (StringUtils.isBlank(userDept)){
                throw new RuntimeException("审批提交失败：你的账号没有设置部门！");  //dept-----error--0
            }

            //设置负责人
            activitiUser.setSubmitName(opalUser.getUserId() + "");
            //设置邮箱变量
            mail.setToMail(opalUser.getUserMail());
        }else {
            throw new RuntimeException("审批提交失败：抱歉，登录已失效！请重新登录操作");
        }

        //2、项目经理：根据当前用户的组织、部门，编号为：1来找；0：普通员工1、项目经理 2、部门经理，3、总经理、4，总裁
        List<OpalUser> user=opalUserService.getOpalUser(pkOrg,userDept,1);
        if (user !=null && user.size()>0){
            activitiUser.setTaskName1(user.get(0).getUserId() + "");  //设置id
            mail.setToMail1(user.get(0).getUserMail());               //设置邮箱地址
        }else {
            throw new RuntimeException("审批提交失败：【澳宝管理系统】中未找到项目经理的账号");
        }
        user=null;

        //3、部门经理：根据当前用户的组织，编号为：2来找；  0：普通员工1、项目经理 2、部门经理，3、总经理、4，总裁，5、内销会计，6、外销会计，7、财务经理,8、成本财务，9、副总经理
        if(pkOrg.equals(CommonConst.AOBAO)){  //澳宝找部门经理
            user=opalUserService.getBuMenJingLiOpalUser(userDept);
        }else {//兆婷找兆婷的副总经理,目前就一个
            user=opalUserService.getOpalUser(pkOrg,9);
        }

        if (user !=null && user.size()>0){
            activitiUser.setTaskName2(user.get(0).getUserId() + "");  //设置id
            mail.setToMail2(user.get(0).getUserMail());               //设置邮箱地址
        }else {
            throw new RuntimeException("审批提交失败：【澳宝管理系统】中未找到部门经理或兆婷副总经理的账号");
        }
        user=null;

        //4、总经理：根据当前用户的组织，编号为：3来找；
        user=opalUserService.getOpalUser(pkOrg,3);
        if (user !=null && user.size()>0){
            activitiUser.setTaskName3(user.get(0).getUserId() + "");
            mail.setToMail3(user.get(0).getUserMail());
        }else {
            throw new RuntimeException("审批提交失败：【澳宝管理系统】中未找到总经理的账号");
        }
        user=null;

        //5、总裁：总裁就一个根据编号为：3来找；
        //处理postcode参数
        user=opalUserService.getOpalUserByUserPosition(4);
        if (user !=null && user.size()>0){
            activitiUser.setTaskName4(user.get(0).getUserId() + "");
            mail.setToMail4(user.get(0).getUserMail());
        }else {
            throw new RuntimeException("审批提交失败：【澳宝管理系统】中未找到总裁的账号");
        }
        user=null;

        return activitiUser;
    }

    private void financeValuation(AcMail acMail,ActivitiUser activitiUser,String saleType,CostReport costReport) {
        //获取公司账套选择的组织
        String pkOrg = costReport.getPkOrgAccount();
        //内销会计:2个
        if("内销".equals(saleType)){
            //根据职位找到所有的内销会计
            List<OpalUser> list= opalUserService.getOpalUser(pkOrg,5);
            if (list == null|| list.size() <=0 ) {
                throw new RuntimeException("审批提交失败：无法转接给相关的财务人员(系统中未找到内销会计的财务人员)");
            }
            //找到的内销财务人数走不同的流程
            int j=list.size();
            if(j>=3){
                activitiUser.setCaiwuCount(3);
            }else {
                activitiUser.setCaiwuCount(j);
            }

            //封装内销会计的id和邮箱地址
            int i=1;
            for (OpalUser o:list){
                switch (i){
                    case 1:
                        activitiUser.setNeiXiaoCaiWu(o.getUserId() + "");       //内销会计id
                        acMail.setNeiXiaoCaiWuMail(o.getUserMail());             //内销会计邮箱
                        break;
                    case 2:
                        activitiUser.setNeiXiaoCaiWu2(o.getUserId() + "");
                        acMail.setNeiXiaoCaiWuMail2(o.getUserMail());
                        break;
                    case 3:
                        activitiUser.setNeiXiaoCaiWu3(o.getUserId() + "");
                        acMail.setNeiXiaoCaiWuMail3(o.getUserMail());
                        break;
                }
                i++;
            }

        }else {
            //外销会计：1
            List<OpalUser> list= opalUserService.getOpalUser(pkOrg,6);
            if (list == null|| list.size() <=0 ) {
                throw new RuntimeException("审批提交失败：无法转接给相关的财务人员(系统中未找到外销会计的财务人员)");
            }
            //找到的外销财务人数走不同的流程
            int j=list.size();
            if(j>=3){
                activitiUser.setCaiwuCount(3);
            }else {
                activitiUser.setCaiwuCount(j);
            }
            int i=1;
            for (OpalUser o:list){
                switch (i){
                    case 1:
                        activitiUser.setWaiXiaoCaiWu(o.getUserId() + "");  //外销会计id
                        acMail.setWaiXiaoCaiWuMail(o.getUserMail());       //外销会计邮箱
                        break;
                    case 2:
                        activitiUser.setWaiXiaoCaiWu2(o.getUserId() + "");  //外销会计id
                        acMail.setWaiXiaoCaiWuMail2(o.getUserMail());       //外销会计邮箱
                        break;
                    case 3:
                        activitiUser.setWaiXiaoCaiWu3(o.getUserId() + "");  //外销会计id
                        acMail.setWaiXiaoCaiWuMail3(o.getUserMail());       //外销会计邮箱
                        break;
                }
                ++i;
            }
        }
    }

    private  OpalUser  isManageInfo( List<Map<String, String>> maps,String name){
        if (maps.size()<=0){
            throw new RuntimeException("审批提交失败：在NC上没有找到当前的"+name+"的工号");
        }
        //根据工号查询mysql中的用户信息
        OpalUser user = this.getUser(maps.get(0).get("CODE"));
        if(user ==null){
            throw new RuntimeException("审批提交失败：在NC上已找到"+name+"的工号，但未在【澳宝管理系统】上找到相关的工号！");
        }else {
            //判断邮箱是否设置   注意 未判断邮箱的格式，
            if (StringUtils.isBlank(user.getUserMail())){
                throw new RuntimeException("审批提交失败：在【澳宝管理系统】上未获取到"+name+"的邮箱信息！");
            }
        }
        return user;
    }

    //根据工号查询mysql中的用户信息
    private OpalUser getUser(String code){
        OpalUserExample opalUserExample = new OpalUserExample();
        opalUserExample.createCriteria().andUserCodeEqualTo(code);
        List<OpalUser> opalUsers = opalUserMapper.selectByExample(opalUserExample);
        if (opalUsers ==null || opalUsers.size()<=0){
            return null;
        }
        return opalUsers.get(0);
    }

    //根据职位和组织查询mysql中的用户信息
    private OpalUser getUser(Integer userPosition,String pkOrg){
        OpalUserExample opalUserExample = new OpalUserExample();
        opalUserExample.createCriteria().andUserPositionEqualTo(userPosition).andPkOrgEqualTo(pkOrg);
        List<OpalUser> opalUsers = opalUserMapper.selectByExample(opalUserExample);
        if (opalUsers ==null || opalUsers.size()<=0){
            return null;
        }
        return opalUsers.get(0);
    }

}
